/*
	编译器对每个包含虚函数的类创建一个表（称为VTABLE）.
	在VTABLE中，编译器放置特定类的虚函数地址。
	在每个带有虚函数的类中，编译器秘密的置一指针，称为vpointer(缩写VPTR),指向这个对象的VTABLE。
	通过基类指针做虚函数调用时(也就是做多态调用时)，编译器静态地插入取得这个VPTR，并在VTABLE表中查找函数地址的代码，这样就能调用正确的函数使晚捆绑发生。


	及函数f具有虚特性的条件：
		在基类中，将该函数说明为虚函数。这样可以在派生类中重新定义此函数，为它赋予新的功能，并能够方便调用。在类外定义虚函数时，不必再加virtual关键字。
		定义基类的公有派生类。
		在基类的公有派生类中原型一致地重载该函数。
		定义指向基类的指针变量，它指向基类的公有派生类的对象（或定义基类的引用，它引用积累的公有派生类的对象。）


	注意:
		以前的函数重载处理的是统一层次上的同名函数问题，而虚函数处理的是不同派生层次的同名函数问题，前者是横向重载，后者是纵向重载。
		如果纵向重载不使用virtual，当基类指针指向不同的派生对象时，访问的只有基类成员函数; 如果派生类访问，则是覆盖同名覆盖，即访问的是派生类对象自己的成员函数。
*/

/*
	Here: 说明虚特性丢失这个问题:
		指：函数原型不同，仅函数名相同，被C++认为是一般的重载.
*/

#include <iostream>

using namespace std;

class base {
	public:
		virtual void vf1();
		virtual void vf2();
		virtual void vf3();
		void f();
};

class derived: public base {
	public:
		void vf1(); // 具有虚特性
		void vf2(int); // 一般函数重载，参数不同，虚特性丢失。
		char vf3();	// 错误，仅放回类型不同.
		void f();	// 一般的函数重载，非需函数的重载
};

void g() {
	derived d;
	base * bp = &d; // 积累指针指向公有派生对象
	bp->vf1();	// 调用derived::vf1();
	bp->vf2(); // 调用base::vf2();
	bp->f(); // 调用base::f();
}

int main(int argc, char * argv[]) {

	g();
	return 0;
}
